const dayjs = require('dayjs');
const { redis } = require('../config/redis_client');
const { Order, OrderStatusLog } = require('../model/Order')
const CoinLedger = require('../model/CoinLedger');
const User = require('../model/User')
const {sequelize} = require("../config/mysql_config");

const KEY_EXPIRE = 'z:order:expire';
const KEY_RUSH = 'z:order:rush';

const ORDER_STATUS = { PENDING: "pending", COMPLETED: "completed", CANCELLED: "cancelled" };

async function scheduleOrderDeadlines({ orderId, expireAt, rushDeadlineAt, isRush }) {
    const scoreExpire = Math.floor(expireAt.getTime() / 1000);
    const scoreRush   = rushDeadlineAt ? Math.floor(rushDeadlineAt.getTime() / 1000) : null;
    await redis.zadd(KEY_EXPIRE, scoreExpire, String(orderId)); //将String(orderId)加入名为KEY_EXPIRE的有序集合，scoreExpire作为分数
    if (isRush && rushDeadlineAt) {
        await redis.zadd(KEY_RUSH, scoreRush, String(orderId));
    }
}

/** 扫描 rush 到期：退加急费 */
async function processRushTimeoutBatch(limit = 100) {
    const now = Math.floor(Date.now() / 1000);
    const ids = await redis.zrangebyscore(KEY_RUSH, 0, now, 'LIMIT', 0, limit);
    if (ids.length === 0) return { scanned: 0, removed: 0, kept: 0 };

    const toRemove = [];
    let kept = 0;

    for (const sid of ids) {
        try {
            const okToRemove = await handleRushTimeout(Number(sid));
            if (okToRemove) toRemove.push(sid);
            else kept++;
        } catch (e) {
            kept++;
            console.error('[rush] handle error for', sid, e);
        }
    }

    if (toRemove.length) await redis.zrem(KEY_RUSH, ...toRemove);
    return { scanned: ids.length, removed: toRemove.length, kept };
}

/** 扫描订单过期：取消并退款 */
async function processOrderExpireBatch(limit = 100) {
    const now = Math.floor(Date.now() / 1000);
    const ids = await redis.zrangebyscore(KEY_EXPIRE, 0, now, 'LIMIT', 0, limit);
    if (ids.length === 0) return { scanned: 0, removed: 0, kept: 0 };

    const toRemove = [];
    let kept = 0;

    for (const sid of ids) {
        try {
            const okToRemove = await handleOrderExpire(Number(sid));
            if (okToRemove) toRemove.push(sid);
            else kept++;
        } catch (e) {
            kept++;
            console.error('[expire] handle error for', sid, e);
        }
    }

    if (toRemove.length) await redis.zrem(KEY_EXPIRE, ...toRemove);
    return { scanned: ids.length, removed: toRemove.length, kept };
}

async function handleRushTimeout(orderId) {
    return await sequelize.transaction(async (t) => {
        const order = await Order.findByPk(orderId, { transaction: t, lock: t.LOCK.UPDATE });
        if (!order) return true; // 订单不存在：把这条从ZSET删掉即可
        if (order.status !== ORDER_STATUS.PENDING) return true; // 非待处理，也删
        if (!order.isRush || order.isRushCanceled) return true; // 没加急或已退过，也删

        const user = await User.findByPk(order.userId, { transaction: t, lock: t.LOCK.UPDATE });
        if (!user) return true; // 找不到用户，也删（或按需记录异常）

        const rushPrice = Number(order.rushPrice || 0);
        const newCoin = Number(user.coin || 0) + rushPrice;
        await user.update({ coin: newCoin }, { transaction: t });
        await CoinLedger.create(
            { accountType:'user', accountId:user.id, orderId:order.id, bizType:'ORDER_RUSH_REFUND', amount:rushPrice, balanceAfter:newCoin },
            { transaction:t }
        );
        await order.update({ isRushCanceled: 1}, { transaction: t });

        return true; // 处理成功，删掉
    });
}

async function handleOrderExpire(orderId) {
    return await sequelize.transaction(async (t) => {
        const order = await Order.findByPk(orderId, { transaction: t, lock: t.LOCK.UPDATE });
        if (!order) return true;
        if (order.status !== ORDER_STATUS.PENDING) return true;

        const from = order.status;
        await order.update({ status: ORDER_STATUS.CANCELLED }, { transaction: t });
        await OrderStatusLog.create(
            { orderId, fromStatus: from, toStatus: ORDER_STATUS.CANCELLED, reasonCode: 'NORMAL_TIMEOUT' },
            { transaction: t }
        );

        const user = await User.findByPk(order.userId, { transaction: t, lock: t.LOCK.UPDATE });
        if (user) {
            const total = Number(order.totalPrice || 0);
            const newCoin = Number(user.coin || 0) + total;
            await user.update({ coin: newCoin }, { transaction: t });
            await CoinLedger.create(
                { accountType:'user', accountId:user.id, orderId:order.id, bizType:'ORDER_REFUND_ALL', amount:total, balanceAfter:newCoin },
                { transaction:t }
            );
        }
        return true;
    });
}

module.exports = {
    scheduleOrderDeadlines,
    processRushTimeoutBatch,
    processOrderExpireBatch,
};